home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / editors / mntemacs.zoo / src / malloc.c < prev    next >
C/C++ Source or Header  |  1991-12-02  |  21KB  |  838 lines

  1. /* dynamic memory allocation for GNU.
  2.    Copyright (C) 1985, 1987 Free Software Foundation, Inc.
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 1, or (at your option)
  7.     any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. In other words, you are welcome to use, share and improve this program.
  19. You are forbidden to forbid anyone else to use, share and improve
  20. what you give them.   Help stamp out software-hoarding!  */
  21.  
  22.  
  23. /*
  24.  * @(#)nmalloc.c 1 (Caltech) 2/21/82
  25.  *
  26.  *    U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs
  27.  *
  28.  *    Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD.
  29.  *
  30.  * This is a very fast storage allocator.  It allocates blocks of a small 
  31.  * number of different sizes, and keeps free lists of each size.  Blocks
  32.  * that don't exactly fit are passed up to the next larger size.  In this 
  33.  * implementation, the available sizes are (2^n)-4 (or -16) bytes long.
  34.  * This is designed for use in a program that uses vast quantities of
  35.  * memory, but bombs when it runs out.  To make it a little better, it
  36.  * warns the user when he starts to get near the end.
  37.  *
  38.  * June 84, ACT: modified rcheck code to check the range given to malloc,
  39.  * rather than the range determined by the 2-power used.
  40.  *
  41.  * Jan 85, RMS: calls malloc_warning to issue warning on nearly full.
  42.  * No longer Emacs-specific; can serve as all-purpose malloc for GNU.
  43.  * You should call malloc_init to reinitialize after loading dumped Emacs.
  44.  * Call malloc_stats to get info on memory stats if MSTATS turned on.
  45.  * realloc knows how to return same block given, just changing its size,
  46.  * if the power of 2 is correct.
  47.  */
  48.  
  49. /*
  50.  * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
  51.  * smallest allocatable block is 8 bytes.  The overhead information will
  52.  * go in the first int of the block, and the returned pointer will point
  53.  * to the second.
  54.  *
  55. #ifdef MSTATS
  56.  * nmalloc[i] is the difference between the number of mallocs and frees
  57.  * for a given block size.
  58. #endif MSTATS
  59.  */
  60.  
  61. #ifdef emacs
  62. /* config.h specifies which kind of system this is.  */
  63. #include "config.h"
  64. #include <signal.h>
  65. #else
  66.  
  67. /* Determine which kind of system this is.  */
  68. #include <signal.h>
  69. #ifndef SIGTSTP
  70. #ifndef VMS
  71. #ifndef USG
  72. #define USG
  73. #endif
  74. #endif /* not VMS */
  75. #else /* SIGTSTP */
  76. #ifdef SIGIO
  77. #define BSD4_2
  78. #endif /* SIGIO */
  79. #endif /* SIGTSTP */
  80.  
  81. #endif /* not emacs */
  82.  
  83. /* Define getpagesize () if the system does not.  */
  84. #include "getpagesize.h"
  85.  
  86. #ifdef BSD
  87. #ifdef BSD4_1
  88. #include <sys/vlimit.h>        /* warn the user when near the end */
  89. #else /* if 4.2 or newer */
  90. #include <sys/time.h>
  91. #include <sys/resource.h>
  92. #endif /* if 4.2 or newer */
  93. #endif
  94.  
  95. #ifdef VMS
  96. #include "vlimit.h"
  97. #endif
  98.  
  99. extern char *start_of_data ();
  100.  
  101. #ifdef BSD
  102. #ifndef DATA_SEG_BITS
  103. #define start_of_data() &etext
  104. #endif
  105. #endif
  106.  
  107. #ifndef emacs
  108. #define start_of_data() &etext
  109. #endif
  110.  
  111. #define ISALLOC ((char) 0xf7)    /* magic byte that implies allocation */
  112. #define ISFREE ((char) 0x54)    /* magic byte that implies free block */
  113.                 /* this is for error checking only */
  114. #define ISMEMALIGN ((char) 0xd6)  /* Stored before the value returned by
  115.                      memalign, with the rest of the word
  116.                      being the distance to the true
  117.                      beginning of the block.  */
  118.  
  119. extern char etext;
  120.  
  121. /* These two are for user programs to look at, when they are interested.  */
  122.  
  123. unsigned int malloc_sbrk_used;       /* amount of data space used now */
  124. unsigned int malloc_sbrk_unused;     /* amount more we can have */
  125.  
  126. /* start of data space; can be changed by calling init_malloc */
  127. static char *data_space_start;
  128.  
  129. #ifdef MSTATS
  130. static int nmalloc[30];
  131. static int nmal, nfre;
  132. #endif /* MSTATS */
  133.  
  134. /* If range checking is not turned on, all we have is a flag indicating
  135.    whether memory is allocated, an index in nextf[], and a size field; to
  136.    realloc() memory we copy either size bytes or 1<<(index+3) bytes depending
  137.    on whether the former can hold the exact size (given the value of
  138.    'index').  If range checking is on, we always need to know how much space
  139.    is allocated, so the 'size' field is never used. */
  140.  
  141. struct mhead {
  142.     char     mh_alloc;    /* ISALLOC or ISFREE */
  143.     char     mh_index;    /* index in nextf[] */
  144. /* Remainder are valid only when block is allocated */
  145.     unsigned short mh_size;    /* size, if < 0x10000 */
  146. #ifdef rcheck
  147.     unsigned mh_nbytes;    /* number of bytes allocated */
  148.     int      mh_magic4;    /* should be == MAGIC4 */
  149. #endif /* rcheck */
  150. };
  151.  
  152. /* Access free-list pointer of a block.
  153.   It is stored at block + 4.
  154.   This is not a field in the mhead structure
  155.   because we want sizeof (struct mhead)
  156.   to describe the overhead for when the block is in use,
  157.   and we do not want the free-list pointer to count in that.  */
  158.  
  159. #define CHAIN(a) \
  160.   (*(struct mhead **) (sizeof (char *) + (char *) (a)))
  161.  
  162. #ifdef rcheck
  163.  
  164. /* To implement range checking, we write magic values in at the beginning and
  165.    end of each allocated block, and make sure they are undisturbed whenever a
  166.    free or a realloc occurs. */
  167. /* Written in each of the 4 bytes following the block's real space */
  168. #define MAGIC1 0x55
  169. /* Written in the 4 bytes before the block's real space */
  170. #define MAGIC4 0x55555555
  171. #define ASSERT(p) if (!(p)) botch("p"); else
  172. #define EXTRA  4        /* 4 bytes extra for MAGIC1s */
  173. #else
  174. #define ASSERT(p) if (!(p)) abort (); else
  175. #define EXTRA  0
  176. #endif /* rcheck */
  177.  
  178.  
  179. /* nextf[i] is free list of blocks of size 2**(i + 3)  */
  180.  
  181. static struct mhead *nextf[30];
  182.  
  183. /* busy[i] is nonzero while allocation of block size i is in progress.  */
  184.  
  185. static char busy[30];
  186.  
  187. /* Number of bytes of writable memory we can expect to be able to get */
  188. static unsigned int lim_data;
  189.  
  190. /* Level number of warnings already issued.
  191.   0 -- no warnings issued.
  192.   1 -- 75% warning already issued.
  193.   2 -- 85% warning already issued.
  194. */
  195. static int warnlevel;
  196.  
  197. /* Function to call to issue a warning;
  198.    0 means don't issue them.  */
  199. static void (*warnfunction) ();
  200.  
  201. /* nonzero once initial bunch of free blocks made */
  202. static int gotpool;
  203.  
  204. char *_malloc_base;
  205.  
  206. static void getpool ();
  207.  
  208. /* Cause reinitialization based on job parameters;
  209.   also declare where the end of pure storage is. */
  210. void
  211. malloc_init (start, warnfun)
  212.      char *start;
  213.      void (*warnfun) ();
  214. {
  215.   if (start)
  216.     data_space_start = start;
  217.   lim_data = 0;
  218.   warnlevel = 0;
  219.   warnfunction = warnfun;
  220. }
  221.  
  222. /* Return the maximum size to which MEM can be realloc'd
  223.    without actually requiring copying.  */
  224.  
  225. int
  226. malloc_usable_size (mem)
  227.      char *mem;
  228. {
  229.   struct mhead *p
  230.     = (struct mhead *) (mem - ((sizeof (struct mhead) + 7) & ~7));
  231.   int blocksize = 8 << p->mh_index;
  232.  
  233.   return blocksize - sizeof (struct mhead) - EXTRA;
  234. }
  235.  
  236. static void
  237. morecore (nu)            /* ask system for more memory */
  238.      register int nu;        /* size index to get more of  */
  239. {
  240.   char *sbrk ();
  241.   register char *cp;
  242.   register int nblks;
  243.   register unsigned int siz;
  244.   int oldmask;
  245.  
  246. #ifdef BSD
  247. #ifndef BSD4_1
  248.   int newmask = -1;
  249.   /* Blocking these signals interferes with debugging, at least on BSD on
  250.      the HP 9000/300.  */
  251. #ifdef SIGTRAP
  252.   newmask &= ~(1 << SIGTRAP);
  253. #endif
  254. #ifdef SIGILL
  255.   newmask &= ~(1 << SIGILL);
  256. #endif
  257. #ifdef SIGTSTP
  258.   newmask &= ~(1 << SIGTSTP);
  259. #endif
  260. #ifdef SIGSTOP
  261.   newmask &= ~(1 << SIGSTOP);
  262. #endif
  263.   oldmask = sigsetmask (newmask);
  264. #endif
  265. #endif
  266.  
  267.   if (!data_space_start)
  268.     {
  269.       data_space_start = start_of_data ();
  270.     }
  271.  
  272.   if (lim_data == 0)
  273.     get_lim_data ();
  274.  
  275.  /* On initial startup, get two blocks of each size up to 1k bytes */
  276.   if (!gotpool)
  277.     { getpool (); getpool (); gotpool = 1; }
  278.  
  279.   /* Find current end of memory and issue warning if getting near max */
  280.  
  281. #ifndef VMS
  282.   /* Maximum virtual memory on VM